package rifl.meres4.commons.step;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;

import org.osgi.service.log.LogService;

import rifl.meres4.commons.model.Software;

public abstract class AbstractWorkflowStep implements IWorkflowStep {

	protected LogService log;
	protected ArrayBlockingQueue<Software> inputQueue = new ArrayBlockingQueue<Software>(10);
	protected List<IWorkflowStep> nextSteps = new ArrayList<IWorkflowStep>();
	protected List<MessageListener> messageListeners = new ArrayList<MessageListener>();
	
	@Override
	public void put(Software software) throws InterruptedException {
		if (this.nextSteps.isEmpty()) {
			if (log != null) {
				log.log(LogService.LOG_ERROR, "Next Services currently unavailable for: " + getClass().getName());
			}
		} else {
			if (log != null) {
				log.log(LogService.LOG_INFO, "Putting messages into nextSteps!");
			}
			for (IWorkflowStep step : nextSteps) {
				step.addToInputQueue(software);				
			}
		}
	}

	@Override
	public Software get() throws InterruptedException {
		return inputQueue.take();
	}

	@Override
	public synchronized void addNextStep(IWorkflowStep step) {
		this.nextSteps.add(step);
	}
	
	@Override
	public synchronized void removeNextStep(IWorkflowStep step) {
		this.nextSteps.remove(step);
	}
	
	@Override
	public synchronized void addToInputQueue(Software software) throws InterruptedException {
		this.inputQueue.put(software);
		notifyMessageListeners(software);
	}
	
	protected void notifyMessageListeners(Software software) {
		for (MessageListener l : messageListeners) {
			l.onMessage(software);
		}
	}

	@Override
	public synchronized void registerMessageListener(MessageListener l) {
		this.messageListeners.add(l);
	}
	
	@Override
	public synchronized void unregisterMessageListener(MessageListener l) {
		this.messageListeners.remove(l);
	}
	
	public void setLog(LogService log) {
		this.log = log;
	}
	
	public void unsetLog(LogService log) {
		this.log = log;
	}
	
	@Override
	public boolean hasInput() {
		return !this.inputQueue.isEmpty();
	}
	
	@Override
	public boolean canDoStep() {
		return !this.nextSteps.isEmpty();
	}
	
}
